package com.edu.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.edu.common.annotation.ImportGroup;
import com.edu.common.exception.ServiceException;
import com.edu.common.utils.StringUtils;
import com.edu.common.utils.bean.BeanUtils;
import com.edu.common.utils.bean.BeanValidators;
import com.edu.system.domain.StudentType;
import com.edu.system.domain.TCard;
import com.edu.system.domain.TClass;
import com.edu.system.domain.dto.StudentDTO;
import com.edu.system.service.IStudentTypeService;
import com.edu.system.service.ISysConfigService;
import com.edu.system.service.ITCardService;
import com.edu.system.service.ITClassService;

import com.edu.system.service.ITCohortService;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.validation.Validator;

import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.edu.system.mapper.StudentMapper;
import com.edu.system.domain.Student;
import com.edu.system.service.IStudentService;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author xxxx
 * @date 2023-12-16
 */
@Slf4j
@Service
public class StudentServiceImpl implements IStudentService
{
    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    protected Validator validator;
    @Resource
    private IStudentTypeService studentTypeService;
    @Resource
    private ITClassService itClassService;
    @Resource
    private ITCardService itCardService;
    @Resource
    private ITCohortService itCohortService;

    /**
     * 查询【请填写功能名称】
     *
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public Student selectStudentById(Long id)
    {
        return studentMapper.selectStudentById(id);
    }

    @Override
    public Student selectStudentByStuNo(String stuNo) {
        Student s = new Student();
        s.setStuNo(stuNo);
        List<Student> students = this.selectStudentList(s);
        return Optional.ofNullable(students)
            .filter(CollectionUtils::isNotEmpty)
            .map(a -> a.get(0))
            .orElseGet(() -> null);
    }

    @Override
    public Student selectStudentByCardNo(String cardNo) {
        TCard card = itCardService.findCardByNo(cardNo);
        return this.selectStudentByStuNo(card.getOwnerId());
    }

    public StudentDTO convertEnumToValue(Student a) {
        StudentDTO dto = BeanUtil.copyProperties(a, StudentDTO.class);
        dto.setStudentType(getStudentTypeName(a.getStudentType()));
        return dto;
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param student 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<Student> selectStudentList(Student student)
    {
        return studentMapper.selectStudentList(student);
    }

    @Override
    public List<StudentDTO> showStudentList(Student student) {
        List<Student> students = studentMapper.selectStudentList(student);
        return converToDTO(students);
    }

    private List<StudentDTO> converToDTO(List<Student> students){
        List<StudentDTO> result;
        if(students instanceof Page){
            result = new Page<>();
            BeanUtils.copyBeanProp(result,students);
        }else {
            result = new ArrayList<>();
        }
        for (Student student : students) {
            result.add(this.convertEnumToValue(student));
        }
        return result;
    }

    @Override
    public List<Student> queryListByNames(List<String> names) {
        return studentMapper.listByNames(names);
    }

    @Override
    public Map<String, Long> queryIdMapByNames(List<String> names) {
        return this.queryListByNames(names)
            .stream()
            .collect(Collectors.toMap(Student::getName, Student::getId, (x,y)->x));
    }

    private String getStudentTypeName(Integer id){
        if (id == null){
            return "";
        }
        return Optional.ofNullable(studentTypeService.selectStudentTypeById(Long.parseLong(id.toString())))
            .map(StudentType::getTypeName)
            .orElseGet(() -> "");
    }
    /**
     * 新增【请填写功能名称】
     *
     * @param s 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertStudent(Student s)
    {
        if (s.getClassId() != null){
            TClass tClass = itClassService.selectTClassById(s.getClassId());
            s.setGeneration(tClass.getCohort());
            s.setClassName(
                Optional.ofNullable(itClassService.selectTClassById(s.getClassId())).map(TClass::getName).orElseGet(()->"")
            );
        }
        return studentMapper.insertStudent(s);
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param student 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateStudent(Student student)
    {
        Student old = this.selectStudentById(student.getId());

        TCard card = itCardService.findCardByOwnerId(old.getStuNo());
        // 更新 卡学号
        if (!old.getStuNo().equals(student.getStuNo())){
            Optional.ofNullable(card).ifPresent(a -> card.setOwnerId(student.getStuNo()));
        }
        // 同步card班级id
        if (!old.getClassId().equals(student.getClassId())){
            Optional.ofNullable(card).ifPresent(a -> card.setClassId(student.getClassId()));
            // 更新 学生班级名称
            TClass tClass = itClassService.selectTClassById(student.getClassId());
            Optional.ofNullable(card).ifPresent(a -> card.setGeneration(tClass.getCohort()));
            student.setClassName(tClass.getName());
            student.setGeneration(tClass.getCohort());
        }
        if (!old.getName().equals(student.getName())){
            Optional.ofNullable(card).ifPresent(a -> card.setOwner(student.getName()));
        }
        Optional.ofNullable(card).ifPresent(a -> itCardService.updateTCard(card));

        return studentMapper.updateStudent(student);
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteStudentByIds(Long[] ids)
    {
        return studentMapper.deleteStudentByIds(ids);
    }

    /**
     * 删除【请填写功能名称】信息
     *
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteStudentById(Long id)
    {
        return studentMapper.deleteStudentById(id);
    }

    @Override
    public long getStudentCnt() {
        return studentMapper.studentCnt();
    }

    @Override
    public List<Student> queryByIds(List<Long> ids) {
        return Optional.ofNullable(ids)
            .filter(CollectionUtils::isNotEmpty)
            .map(a -> studentMapper.listByIds(a))
            .orElseGet(Lists::newArrayList);
    }

    @Override
    public List<Student> queryByStuNos(List<String> stuNos) {
        return studentMapper.listByStuNos(stuNos);
    }


    @Override
    public List<List<String>> matrixNameById(List<List<Long>> ids) {
        List<Long> idList = ids.stream().flatMap(Collection::stream).collect(Collectors.toList());

        Map<Long, String> collect = this.queryByIds(idList).stream()
            .collect(Collectors.toMap(Student::getId, Student::getName, (x, y) -> x));

        return ids.stream().map(a ->
            a.stream().map(b -> collect.getOrDefault(b, "")).collect(Collectors.toList())
        ).collect(Collectors.toList());

    }

    /**
     * 导入学生数据
     *
     * @param sList        数据列表
     * @param operName     操作用户
     * @return 结果
     */
    @Override
    public String importStudent(List<Student> sList, String operName) {
        if (StringUtils.isNull(sList) || sList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (Student s : sList) {
            try {
                // 验证是否存在这个用户
                Student student = checkIsExist(s.getName(), s.getStuNo());
                if (StringUtils.isNull(student)) {
                    BeanValidators.validateWithException(validator, s, ImportGroup.class);
                    // 补充数据
                    checkAndFormatData(s);

                    studentMapper.insertStudent(s);
                    successNum++;
//                    successMsg.append("<br/>" + successNum + "、学生 " + s.getName() + " 导入成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、学生 " + s.getName() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、学生 " + s.getName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            failureMsg.insert(0, "导入成功，共 " + successNum + " 条。<br/>");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }


    private void checkAndFormatData(Student s) throws Exception {
        TClass tClass = new TClass();
        tClass.setCohort(s.getGeneration());
        tClass.setName(s.getClassName());
        List<TClass> tClasses = itClassService.selectRealList(tClass);
        if (CollectionUtils.isEmpty(tClasses)){
            throw new Exception("班级未找到");
        }
        s.setClassId(tClasses.get(0).getId());
    }

    public Student checkIsExist(String name, String stuNo) {
        Student t = new Student();
        t.setName(name);
        t.setStuNo(stuNo);
        List<Student> list = studentMapper.realSearchStudentList(t);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }
    @Override
    public int countStudentNum(Student student) {
    	return studentMapper.countStudentNum(student);
    }
}
